//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by FernFlower decompiler)
//

package org.activiti.engine.impl.bpmn.behavior;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import org.activiti.bpmn.model.Activity;
import org.activiti.bpmn.model.BoundaryEvent;
import org.activiti.bpmn.model.CompensateEventDefinition;
import org.activiti.bpmn.model.FlowElement;
import org.activiti.bpmn.model.FlowNode;
import org.activiti.bpmn.model.Process;
import org.activiti.engine.ActivitiIllegalArgumentException;
import org.activiti.engine.delegate.BpmnError;
import org.activiti.engine.delegate.DelegateExecution;
import org.activiti.engine.delegate.Expression;
import org.activiti.engine.delegate.event.ActivitiEventType;
import org.activiti.engine.delegate.event.impl.ActivitiEventBuilder;
import org.activiti.engine.impl.bpmn.helper.ErrorPropagation;
import org.activiti.engine.impl.context.Context;
import org.activiti.engine.impl.delegate.ActivityBehavior;
import org.activiti.engine.impl.delegate.SubProcessActivityBehavior;
import org.activiti.engine.impl.persistence.entity.ExecutionEntity;
import org.activiti.engine.impl.util.CollectionUtil;
import org.activiti.engine.impl.util.ProcessDefinitionUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public abstract class MultiInstanceActivityBehavior extends FlowNodeActivityBehavior implements SubProcessActivityBehavior {
  private static final long serialVersionUID = 1L;
  protected static final Logger LOGGER = LoggerFactory.getLogger(MultiInstanceActivityBehavior.class);
  protected static final String NUMBER_OF_INSTANCES = "nrOfInstances";
  protected static final String NUMBER_OF_ACTIVE_INSTANCES = "nrOfActiveInstances";
  protected static final String NUMBER_OF_COMPLETED_INSTANCES = "nrOfCompletedInstances";
  protected Activity activity;
  protected AbstractBpmnActivityBehavior innerActivityBehavior;
  protected Expression loopCardinalityExpression;
  protected Expression completionConditionExpression;
  protected Expression collectionExpression;
  protected String collectionVariable;
  protected String collectionElementVariable;
  protected String collectionElementIndexVariable = "loopCounter";
  private String loopDataOutputRef;
  private String outputDataItem;

  public MultiInstanceActivityBehavior(Activity activity, AbstractBpmnActivityBehavior innerActivityBehavior) {
    this.activity = activity;
    this.setInnerActivityBehavior(innerActivityBehavior);
  }

  public void execute(DelegateExecution execution) {
    if (this.getLocalLoopVariable(execution, this.getCollectionElementIndexVariable()) == null) {
      int nrOfInstances = 0;

      try {
        nrOfInstances = this.createInstances(execution);
      } catch (BpmnError var4) {
        ErrorPropagation.propagateError(var4, execution);
      }

      if (nrOfInstances == 0) {
        super.leave(execution);
      }
    } else {
      Context.getCommandContext().getHistoryManager().recordActivityStart((ExecutionEntity)execution);
      this.innerActivityBehavior.execute(execution);
    }

  }

  protected abstract int createInstances(DelegateExecution var1);

  protected void executeCompensationBoundaryEvents(FlowElement flowElement, DelegateExecution execution) {
    Collection<BoundaryEvent> boundaryEvents = this.findBoundaryEventsForFlowNode(execution.getProcessDefinitionId(), flowElement);
    if (CollectionUtil.isNotEmpty(boundaryEvents)) {
      Iterator var4 = boundaryEvents.iterator();

      while(var4.hasNext()) {
        BoundaryEvent boundaryEvent = (BoundaryEvent)var4.next();
        if (!CollectionUtil.isEmpty(boundaryEvent.getEventDefinitions()) && boundaryEvent.getEventDefinitions().get(0) instanceof CompensateEventDefinition) {
          ExecutionEntity childExecutionEntity = Context.getCommandContext().getExecutionEntityManager().createChildExecution((ExecutionEntity)execution);
          childExecutionEntity.setParentId(execution.getId());
          childExecutionEntity.setCurrentFlowElement(boundaryEvent);
          childExecutionEntity.setScope(false);
          ActivityBehavior boundaryEventBehavior = (ActivityBehavior)boundaryEvent.getBehavior();
          boundaryEventBehavior.execute(childExecutionEntity);
        }
      }
    }

  }

  protected Collection<BoundaryEvent> findBoundaryEventsForFlowNode(String processDefinitionId, FlowElement flowElement) {
    Process process = this.getProcessDefinition(processDefinitionId);
    List<BoundaryEvent> results = new ArrayList(1);
    Collection<BoundaryEvent> boundaryEvents = process.findFlowElementsOfType(BoundaryEvent.class, true);
    Iterator var6 = boundaryEvents.iterator();

    while(var6.hasNext()) {
      BoundaryEvent boundaryEvent = (BoundaryEvent)var6.next();
      if (boundaryEvent.getAttachedToRefId() != null && boundaryEvent.getAttachedToRefId().equals(flowElement.getId())) {
        results.add(boundaryEvent);
      }
    }

    return results;
  }

  protected Process getProcessDefinition(String processDefinitionId) {
    return ProcessDefinitionUtil.getProcess(processDefinitionId);
  }

  public void trigger(DelegateExecution execution, String signalName, Object signalData) {
    this.innerActivityBehavior.trigger(execution, signalName, signalData);
  }

  public void lastExecutionEnded(DelegateExecution execution) {
    this.leave(execution);
  }

  public void completing(DelegateExecution execution, DelegateExecution subProcessInstance) throws Exception {
  }

  public void completed(DelegateExecution execution) throws Exception {
    this.leave(execution);
  }

  protected int resolveNrOfInstances(DelegateExecution execution) {
    if (this.loopCardinalityExpression != null) {
      return this.resolveLoopCardinality(execution);
    } else if (this.usesCollection()) {
      Collection collection = this.resolveAndValidateCollection(execution);
      return collection.size();
    } else {
      throw new ActivitiIllegalArgumentException("Couldn't resolve collection expression nor variable reference");
    }
  }

  protected void executeOriginalBehavior(DelegateExecution execution, int loopCounter) {
    if (this.usesCollection() && this.collectionElementVariable != null) {
      Collection collection = (Collection)this.resolveCollection(execution);
      Object value = null;
      int index = 0;

      for(Iterator it = collection.iterator(); index <= loopCounter; ++index) {
        value = it.next();
      }

      this.setLoopVariable(execution, this.collectionElementVariable, value);
    }

    execution.setCurrentFlowElement(this.activity);
    Context.getAgenda().planContinueMultiInstanceOperation((ExecutionEntity)execution);
  }

  protected Collection resolveAndValidateCollection(DelegateExecution execution) {
    Object obj = this.resolveCollection(execution);
    if (this.collectionExpression != null) {
      if (!(obj instanceof Collection)) {
        throw new ActivitiIllegalArgumentException(this.collectionExpression.getExpressionText() + "' didn't resolve to a Collection");
      }
    } else {
      if (this.collectionVariable == null) {
        throw new ActivitiIllegalArgumentException("Couldn't resolve collection expression nor variable reference");
      }

      if (obj == null) {
        throw new ActivitiIllegalArgumentException("Variable " + this.collectionVariable + " is not found");
      }

      if (!(obj instanceof Collection)) {
        throw new ActivitiIllegalArgumentException("Variable " + this.collectionVariable + "' is not a Collection");
      }
    }

    return (Collection)obj;
  }

  protected Object resolveCollection(DelegateExecution execution) {
    Object collection = null;
    if (this.collectionExpression != null) {
      collection = this.collectionExpression.getValue(execution);
    } else if (this.collectionVariable != null) {
      collection = execution.getVariable(this.collectionVariable);
    }

    return collection;
  }

  protected boolean usesCollection() {
    return this.collectionExpression != null || this.collectionVariable != null;
  }

  protected boolean isExtraScopeNeeded(FlowNode flowNode) {
    return flowNode.getSubProcess() != null;
  }

  protected int resolveLoopCardinality(DelegateExecution execution) {
    Object value = this.loopCardinalityExpression.getValue(execution);
    if (value instanceof Number) {
      return ((Number)value).intValue();
    } else if (value instanceof String) {
      return Integer.valueOf((String)value);
    } else {
      throw new ActivitiIllegalArgumentException("Could not resolve loopCardinality expression '" + this.loopCardinalityExpression.getExpressionText() + "': not a number nor number String");
    }
  }

  protected boolean completionConditionSatisfied(DelegateExecution execution) {
    if (this.completionConditionExpression != null) {
      Object value = this.completionConditionExpression.getValue(execution);
      if (!(value instanceof Boolean)) {
        throw new ActivitiIllegalArgumentException("completionCondition '" + this.completionConditionExpression.getExpressionText() + "' does not evaluate to a boolean value");
      } else {
        Boolean booleanValue = (Boolean)value;
        if (LOGGER.isDebugEnabled()) {
          LOGGER.debug("Completion condition of multi-instance satisfied: {}", booleanValue);
        }

        return booleanValue;
      }
    } else {
      return false;
    }
  }

  protected void setLoopVariable(DelegateExecution execution, String variableName, Object value) {
    execution.setVariableLocal(variableName, value);
  }

  protected Integer getLoopVariable(DelegateExecution execution, String variableName) {
    Object value = execution.getVariableLocal(variableName);

    for(DelegateExecution parent = execution.getParent(); value == null && parent != null; parent = parent.getParent()) {
      value = parent.getVariableLocal(variableName);
    }

    return (Integer)(value != null ? value : 0);
  }

  protected Integer getLocalLoopVariable(DelegateExecution execution, String variableName) {
    return (Integer)execution.getVariableLocal(variableName);
  }

  protected void removeLocalLoopVariable(DelegateExecution execution, String variableName) {
    execution.removeVariableLocal(variableName);
  }

  protected void callActivityEndListeners(DelegateExecution execution) {
    Context.getCommandContext().getProcessEngineConfiguration().getListenerNotificationHelper().executeExecutionListeners(this.activity, execution, "end");
  }

  protected void logLoopDetails(DelegateExecution execution, String custom, int loopCounter, int nrOfCompletedInstances, int nrOfActiveInstances, int nrOfInstances) {
    if (LOGGER.isDebugEnabled()) {
      LOGGER.debug("Multi-instance '{}' {}. Details: loopCounter={}, nrOrCompletedInstances={},nrOfActiveInstances={},nrOfInstances={}", new Object[]{execution.getCurrentFlowElement() != null ? execution.getCurrentFlowElement().getId() : "", custom, loopCounter, nrOfCompletedInstances, nrOfActiveInstances, nrOfInstances});
    }

  }

  protected DelegateExecution getMultiInstanceRootExecution(DelegateExecution executionEntity) {
    DelegateExecution multiInstanceRootExecution = null;
    DelegateExecution currentExecution = executionEntity;

    while(currentExecution != null && multiInstanceRootExecution == null && currentExecution.getParent() != null) {
      if (currentExecution.isMultiInstanceRoot()) {
        multiInstanceRootExecution = currentExecution;
      } else {
        currentExecution = currentExecution.getParent();
      }
    }

    return multiInstanceRootExecution;
  }

  protected void dispatchActivityCompletedEvent(DelegateExecution execution) {
    ExecutionEntity executionEntity = (ExecutionEntity)execution;
    Context.getCommandContext().getEventDispatcher().dispatchEvent(ActivitiEventBuilder.createActivityEvent(ActivitiEventType.ACTIVITY_COMPLETED, executionEntity.getActivityId(), executionEntity.getName(), executionEntity.getId(), executionEntity.getProcessInstanceId(), executionEntity.getProcessDefinitionId(), executionEntity.getCurrentFlowElement()));
  }

  public Expression getLoopCardinalityExpression() {
    return this.loopCardinalityExpression;
  }

  public void setLoopCardinalityExpression(Expression loopCardinalityExpression) {
    this.loopCardinalityExpression = loopCardinalityExpression;
  }

  public Expression getCompletionConditionExpression() {
    return this.completionConditionExpression;
  }

  public void setCompletionConditionExpression(Expression completionConditionExpression) {
    this.completionConditionExpression = completionConditionExpression;
  }

  public Expression getCollectionExpression() {
    return this.collectionExpression;
  }

  public void setCollectionExpression(Expression collectionExpression) {
    this.collectionExpression = collectionExpression;
  }

  public String getCollectionVariable() {
    return this.collectionVariable;
  }

  public void setCollectionVariable(String collectionVariable) {
    this.collectionVariable = collectionVariable;
  }

  public String getCollectionElementVariable() {
    return this.collectionElementVariable;
  }

  public void setCollectionElementVariable(String collectionElementVariable) {
    this.collectionElementVariable = collectionElementVariable;
  }

  public String getCollectionElementIndexVariable() {
    return this.collectionElementIndexVariable;
  }

  public void setCollectionElementIndexVariable(String collectionElementIndexVariable) {
    this.collectionElementIndexVariable = collectionElementIndexVariable;
  }

  public void setInnerActivityBehavior(AbstractBpmnActivityBehavior innerActivityBehavior) {
    this.innerActivityBehavior = innerActivityBehavior;
    this.innerActivityBehavior.setMultiInstanceActivityBehavior(this);
  }

  public AbstractBpmnActivityBehavior getInnerActivityBehavior() {
    return this.innerActivityBehavior;
  }

  public String getLoopDataOutputRef() {
    return this.loopDataOutputRef;
  }

  public boolean hasLoopDataOutputRef() {
    return this.loopDataOutputRef != null && !this.loopDataOutputRef.trim().isEmpty();
  }

  public void setLoopDataOutputRef(String loopDataOutputRef) {
    this.loopDataOutputRef = loopDataOutputRef;
  }

  public String getOutputDataItem() {
    return this.outputDataItem;
  }

  public void setOutputDataItem(String outputDataItem) {
    this.outputDataItem = outputDataItem;
  }

  protected void updateResultCollection(DelegateExecution childExecution, DelegateExecution miRootExecution) {
    if (miRootExecution != null && this.hasLoopDataOutputRef()) {
      Object loopDataOutputReference = miRootExecution.getVariableLocal(this.getLoopDataOutputRef());
      Object resultCollection;
      if (loopDataOutputReference instanceof List) {
        resultCollection = (List)loopDataOutputReference;
      } else {
        resultCollection = new ArrayList();
      }

      ((List)resultCollection).add(childExecution.getVariable(this.getOutputDataItem()));
      this.setLoopVariable(miRootExecution, this.getLoopDataOutputRef(), resultCollection);
    }

  }

  protected void propagateLoopDataOutputRefToProcessInstance(ExecutionEntity miRootExecution) {
    if (this.hasLoopDataOutputRef()) {
      miRootExecution.getProcessInstance().setVariable(this.getLoopDataOutputRef(), miRootExecution.getVariable(this.getLoopDataOutputRef()));
    }

  }
}
